#!/bin/bash

# This is for TheGrove
# Merge intro + live + outro


#set default values to be used when not passed as command line options
defaultIntroFile=/Users/Shared/MasterDvdContentFolder/intro.mp4
defaultOutroFile=/Users/Shared/MasterDvdContentFolder/outro.mp4
defaultAudioTrack=/Users/Shared/MasterDvdContentFolder/audiotrack.mp3

# the default value used when --loopCount is not specified
defaultLoopCount=0

# the default value used when --timeLapse is not specified
defaultTimeLapse=0.40

# the default value used when --outputSize is not specified
defaultOutputSize=1280x720
# defaultOutputSize=1920x1080

# the default value used when --frameRate is not specified
defaultFrameRate=30

# the default value used when --compression is not specified
defaultCompression=28

# the default value used when --preset is not specified
defaultPreset=superfast

# the default value used when --preset is not specified
defaultAudio=noAudio

# default value for audioStartTime
defaultAudioStartTime=0.0


#########################################
##### DO NOT MODIFY BELOW THIS LINE #####
#########################################
usage () {
    echo 'usage: <path_to_this_file> --inputFile <path_to_input_file> --outputFile <path_to_output_file> [ --outputSize <1280x720 etc...> ] [ --frameRate <frames_per_sec> ] [ --compression <1 to FLOAT_MAX> ]'
}
die () {
    echo FATAL ERROR: $@ >&2
    usage
    exit 1;
}
#set the PATH to include /usr/local/bin
if test "$PATH" = "${PATH//\/usr\/local\/bin}"; then
  export PATH=/usr/local/bin:$PATH
fi
declare -i squareOutput=0

# parse arguments for recognized flags
while (( $# > 0 )) ; do
 echo $1 = $2
 case "$1" in
    -a|--audioStartTime)
    audioStartTime="$2"
    shift # past argument
    ;;
    -n|--introFile)
    introFile="$2"
    shift # past argument
    ;;
    -u|--outroFile)
    outroFile="$2"
    shift # past argument
    ;;
    -i|--inputFile)
    inputFile="$2"
    shift # past argument
    ;;
    -o|--outputFile)
    outputFile="$2"
    shift # past argument
    ;;
    -v|--overlayFile)
    overlayFile="$2"
    shift # past argument
    ;;
    -l|--loopCount)
    loopCount="$2"
    shift # past argument
    ;;
    -t|--timeLapse)
    timeLapse="$2"
    shift # past argument
    ;;
    -p|--preset)
    preset="$2"
    shift # gobble up $2 argument
    ;;
    -s|--outputSize)
    outputSize="$2"
    shift # gobble up $2 argument
    ;;
    -r|--frameRate)
    frameRate="$2"
    shift # gobble up $2 argument
    ;;
    -c|--compression)
    compression="$2"
    shift # gobble up $2 argument
    ;;
    -b|--thumbnailTimeStamp)
    timeStamp="$2"
    shift # gobble up $2 argument
    ;;
    -q|--square)
#    squareOutput=1
    skwear="-vf \"crop='if(gt(iw,ih),ih,iw)':'if(gt(iw,ih),ih,iw)':'if(gt(iw,ih),(iw-ih)/2,(ih-iw)/2)':0\""
    skwear="-vf \"crop='if(gt(iw,ih),ih,iw)':'if(gt(iw,ih),ih,iw)'\""
    skwear=YES
    ;;
    -w|--withAudio)
        audioFormat="-c:a libfdk_aac -ac 2 -ar 48000 -af aresample=async=2"
    ;;
    *)
    # unknown option
    echo unrecognized option $1
    break
    ;;
 esac
 shift # past argument or value
done

#check for fixed arguments usage
if test -z "${inputFile}" && (($# == 5)); then
 echo using fixed arguments
 #arg 1 is path to input file
 inputFile="${1}"

 #arg 2 is path to input file
 outputFile="${2}"

 #arg 3 is overlay file path
 overlayFile="${3}"

 #arg 4 is loop count (a loop is forward and reverse)
 loopCount="${4:-3}"

 #arg 5 is pts (timeLapse)
 timeLapse="${5:-0.4}"

fi

#error check the input arguments

# verify input file
test -r "${inputFile}" || die unreadable input file "${inputFile}"
#verify output path
test "${outputFile}" || die you must specify an output file path
#verify overlay file type
if test "${overlayFile}"; then
 overlayFileType=$(file  "${overlayFile}")
 test "${overlayFileType}" != "${overlayFileType//PNG image data}" || die overlay files must be PNG type
fi
#validate loopCount
if test -z "${loopCount}" ;then
 loopCount=$defaultLoopCount
 echo "--loopCount = $loopCount (using default value)"
fi
#validate timeLapse
if test -z "${timeLapse}" ;then
     timeLapse=$defaultTimeLapse
     echo "--timeLapse = $timeLapse (using default value)"
fi
#validate outputSize
if test -z "${outputSize}" ;then
    outputSize=$defaultOutputSize
    echo "--outputSize = $outputSize (using default value)"
fi
#validate frameRate
if test -z "${frameRate}" ;then
    frameRate=$defaultFrameRate
    echo "--frameRate = $frameRate (using default value)"
fi
#validate compression
if test -z "${compression}" ;then
    compression=$defaultCompression
    echo "--compression = $compression (using default value)"
fi
#validate preset
if test -z "${preset}" ;then
    preset=$defaultPreset
    echo "--preset = $preset (using default value)"
fi
#validate introFile
if test -z "${introFile}" ;then
    introFile=$defaultIntroFile
    echo "--introfile = $introFile (using default value)"
fi
#validate outroFile
if test -z "${outroFile}" ;then
    outroFile=$defaultOutroFile
    echo "--outrofile = $outroFile (using default value)"
fi
#validate audioStartTime
if test -z "${audioStartTime}" ;then
audioStartTime=$defaultAudioStartTime
echo "--audioStartTime = $audioStartTime (using default value)"
fi

#0. may need to encode to specs first

inputFileBase="${inputFile//.m??}"

#set file extension automatically
fileExt="${inputFile//${inputFileBase}}"


# get the input movie WIDTH and HEIGHT and AUDIO start time in one shot
eval $(ffprobe -v error -show_streams "${inputFile}" | awk -F "=" '/^codec_type=/ {isAudio=($NF=="audio")};/^width/ {if(!isAudio)print "tempmovieWidth=" $NF};/^height/ {if(!isAudio)print "tempmovieHeight=" $NF};/^start_time/ {if(isAudio)print "tempaudiostarttime=" $NF}')
#tempmovieWidth=$(ffprobe -v error -select_streams v:0 -show_streams "${inputFile}" | grep '^width' | awk -F "=" '{printf $2}')
#tempmovieHeight=$(ffprobe -v error -select_streams v:0 -show_streams "${inputFile}" | grep '^height' | awk -F "=" '{printf $2}')
if test -z "${tempmovieWidth}" ;then
    tempmovieWidth=$(echo $defaultOutputSize | awk -F "x" '{printf $1}')
    echo "tempmovieWidth forced to ${tempmovieWidth}"
fi
if test -z "${tempmovieHeight}" ;then
    tempmovieHeight=$(echo $defaultOutputSize | awk -F "x" '{printf $2}')
    echo "tempmovieHeight forced to ${tempmovieHeight}"
fi
outputSize="${tempmovieWidth}x${tempmovieHeight}" # Setting WIDTHxHeight from input source movie file
echo "outputSize from input source => ${outputSize}"


settings="${preset}.${frameRate}.${compression}.${outputSize}" #add outputSize esp if they go from 720 to 1080 movies
#0000 transcode intro/outro if necessary
fileIntro=/Users/Shared/MasterDvdContentFolder/.intro."${settings}".mp4
#test -r "${fileIntro}" || { ffmpeg -nostats -loglevel error -i "${defaultIntroFile}" -pix_fmt yuv420p -preset "${preset}" -r "${frameRate}" -crf "${compression}" -s "${outputSize}" -y "${fileIntro}" ; }
test -r "${fileIntro}" || { ffmpeg -nostats -loglevel error -i "${introFile}" -pix_fmt yuv420p -preset "${preset}" -r "${frameRate}" -crf "${compression}" -s "${outputSize}" -y "${fileIntro}" ; }

fileOutro=/Users/Shared/MasterDvdContentFolder/.outro."${settings}".mp4
#test -r "${fileOutro}" || { ffmpeg -nostats -loglevel error -i "${defaultOutroFile}" -pix_fmt yuv420p -preset "${preset}" -r "${frameRate}" -crf "${compression}" -s "${outputSize}" -y "${fileOutro}" ; }
test -r "${fileOutro}" || { ffmpeg -nostats -loglevel error -i "${outroFile}" -pix_fmt yuv420p -preset "${preset}" -r "${frameRate}" -crf "${compression}" -s "${outputSize}" -y "${fileOutro}" ; }


# get start_time of audio track from input movie
#WORKS tempaudiostarttime=$(ffprobe -v error -select_streams a:0 -show_streams "${inputFile}" | grep 'start_time')
#tempaudiostarttime=$(ffprobe -v error -select_streams a:0 -show_streams "${inputFile}" | grep 'start_time' | awk -F "=" '{printf $2}')
if test -z "${tempaudiostarttime}" ;then
    tempaudiostarttime=${defaultAudioStartTime}
    echo "tempaudiostarttime forced to ${tempaudiostarttime}"
else
    echo "tempaudiostarttime from input source => ${tempaudiostarttime}"
    audioStartTime=${tempaudiostarttime}
fi
echo "audioStartTime => ${audioStartTime}"

#000 convert audio if necessary
if ((0)); then
inputFileAudio=/Users/Shared/MasterDvdContentFolder/audiotrack.aac
test -r "${inputFileAudio}" || { ffmpeg -i "${defaultAudioTrack}"  -c:a libfdk_aac  -y "${inputFileAudio}" ; }
fi
#00. convert to skware
workFile00="${inputFileBase}.noAudio.sizeToFit${fileExt}"
if test "${skwear}";then
ffmpeg -nostats -loglevel error -i "${inputFile}" -pix_fmt yuv420p -preset "${preset}" -r "${frameRate}" -crf "${compression}" -vf "scale=(iw*sar)*max(1080/(iw*sar)\,1080/ih):ih*max(1080/(iw*sar)\,1080/ih), crop=1080:1080" -c:v libx264 -an -y "${workFile00}"
else
ffmpeg -nostats -loglevel error -ss "${audioStartTime}" -i "${inputFile}" -pix_fmt yuv420p -preset "${preset}" -r "${frameRate}" -crf "${compression}" -c:v libx264 "${workFile00}"
fi
#0. concat videos and add audio
workFile0="${inputFileBase}.concatWithNoAudio${fileExt}"
#ffmpeg -nostats -loglevel error -i /Users/Shared/MasterDvdContentFolder/intro.mp4 -i "${workFile00}" -i /Users/Shared/MasterDvdContentFolder/outro.mp4 -i /Users/Shared/MasterDvdContentFolder/audiotrack.mp3 -pix_fmt yuv420p -preset "${preset}" -r "${frameRate}" -crf "${compression}" -filter_complex 'concat=n=3:v=1:a=0[out]' -map '[out]' -map 3 -c:a aac -strict -2 -y "${workFile0}"

#make a thumbnail
if test "${timeStamp}" ;then
    ffmpeg -nostats -loglevel error -i "${workFile00}" -y -ss "${timeStamp}" -f image2 -vframes 1  "${outputFile}".jpg
fi

#######
#ffmpeg -i edv_g24_2.mp4 -i short-video.mp4 -filter_complex
#"[0:v]trim=0:10,setpts=PTS-STARTPTS[v0]; \
#[0:a]atrim=0:10,asetpts=PTS-STARTPTS[a0]; \
#[1:v]trim=0:5,setpts=PTS-STARTPTS[v1]; \
#[1:a]atrim=0:5,asetpts=PTS-STARTPTS[v1]; \
#[0:v]trim=15:30,setpts=PTS-STARTPTS[v2]; \
#[0:a]atrim=15:30,asetpts=PTS-STARTPTS[a2]; \
#[v0][a0][v1][a1][v2][a2]concat=n=3:v=1:a=1[outv][outa]" \
#-map "[outv]" -map "[outa]" output.mp4
#######

# fast concat the video files with no audio
#ffmpeg -nostats -loglevel error -auto_convert 1 -f concat -safe 0 -i <(printf "file %s\n" "${fileIntro}" "${workFile00}" /"${fileOutro}") -codec copy -an -y "${workFile0}"

# fast concat the video files WITH audios
#steve replaced ffmpeg -nostats -loglevel error -auto_convert 1 -f concat -safe 0 -i <(printf "file %s\n" "${fileIntro}" "${workFile00}" /"${fileOutro}") -codec copy -y "${workFile0}"


#tyler version
if test -r "${introFile}" -o -r "${outroFile}" ;then
    echo "One of Intro or Outro exists - must do MERGING";
    concatList=
    test -r "${introFile}" && concatList+="file '${fileIntro}'"$'\n'
    concatList+="file '${workFile00}'"$'\n'
    test -r "${outroFile}" && concatList+="file '${fileOutro}'"$'\n'

    ffmpeg -nostats -loglevel error -auto_convert 1 -f concat -safe 0 -i  <(echo "${concatList}") -codec copy -y "${workFile0}";
else
    echo "NEITHER exists - NO MERGING";
    workFile0="${workFile00}"
fi
# STEVE's version
#if test -r "${introFile}" && test -r "${outroFile}" ;then
#    echo "BOTH exists - CONCAT INTRO and OUTRO...";
#    ffmpeg -nostats -loglevel error -auto_convert 1 -f concat -safe 0 -i <(printf "file \"%s\"\n" "${fileIntro}" "${workFile00}" "${fileOutro}") -codec copy -y "${workFile0}";
#else
#    echo "one or both missing" ;
#    if test -r "${introFile}" ; then
#        # only intro exists
#        echo "intro exists - CONCAT INTRO only...";
#        ffmpeg -nostats -loglevel error -auto_convert 1 -f concat -safe 0 -i <(printf "file \"%s\"\n" "${fileIntro}" "${workFile00}") -codec copy -y "${workFile0}";
#    else
#        if test -r "${outroFile}" ; then
#            # only OUTRO exists
#            echo "outro exists - CONCAT OUTRO only...";
#            ffmpeg -nostats -loglevel error -auto_convert 1 -f concat -safe 0 -i <(printf "file \"%s\"\n" "${workFile00}" "${fileOutro}") -codec copy -y "${workFile0}";
#        else
#            echo "NEITHER exists - NO MERGING just copy...";
#            cp "${workFile00}" "${workFile0}"
#        fi
#    fi
#fi



workFile1="${inputFileBase}.final${fileExt}"

## last step ( merge video and audio tracks and cut to shortest )
#ffmpeg -nostats -loglevel error -i "${workFile0}" -stream_loop -1 -i "${inputFileAudio}" -map 0:v -map 1:a -c copy -bsf:a aac_adtstoasc -shortest -y "${workFile1}"

#just copy instead of adding audio track
workFile1="${workFile0}"

#cp "${workFile0}" "${workFile1}"


# skip the rest for now
if true; then
    cp "${workFile1}" "${outputFile}"
else

    #2. time lapse
    if((loopCount > 0)); then
        workFile2="${inputFileBase}.timeLapse${fileExt}"
        ffmpeg -nostats -loglevel error -i "${workFile1}" -filter_complex "[0:v]setpts=${timeLapse:-0.25}*PTS[v]" -map "[v]" -y "${workFile2}"
    else
        workFile2="${workFile1}"
    fi

    #3. make it square
    if((squareOutput)); then
        echo converting output to square crop
        workFile3="${inputFileBase}.square${fileExt}"
        ffmpeg -nostats -loglevel error -i "${workFile2}"  -vf "crop='if(gt(iw,ih),ih,iw)':'if(gt(iw,ih),ih,iw)'" -y "${workFile3}"
    else
        workFile3="${workFile2}"
    fi
        #4. overlay

    if test -r "${overlayFile}"; then
        workFile4="${inputFileBase}.overlay${fileExt}"
    #    ffmpeg -nostats -loglevel error -i "${workFile3}" -i "${overlayFile}" -filter_complex "[0:v]overlay=:0[v]" -map "[v]" -y "${workFile4}"
    ffmpeg -nostats -loglevel error -i "${workFile3}" -i "${overlayFile}" -filter_complex "overlay" -y "${workFile4}"
    else
        workFile4="${workFile3}"
    fi


        #fwd1-rev1-fwd2-rev2-fwd3-rev3…fwdN-revN
    if((loopCount > 0)); then
        #5.reverse
        workFile5="${inputFileBase}.reverse${fileExt}"
        ffmpeg -nostats -loglevel error -i "${workFile4}" -filter_complex "[0:v]reverse[v]" -map "[v]" -y "${workFile5}"
        #6. concat it n-times
        workFile6="${inputFileBase}.looper${fileExt}"
        ffmpeg -nostats -loglevel error -f concat -safe 0 -i <(for (( ((i=0)) ; ((i<loopCount)) ; ((i++)) )) ; do printf "file %s\n" "${workFile4}" "${workFile5}" ; done) -c copy -y "${workFile6}"
    else
      workFile6="${workFile4}"
    fi
    # move product to output path
    cp "${workFile6}" "${outputFile}"
fi

rm -rf "${workFile00}"
rm -rf "${workFile0}"
rm -rf "${workFile1}"
rm -rf "${workFile2}"
rm -rf "${workFile3}"
rm -rf "${workFile4}"
rm -rf "${workFile5}"
rm -rf "${workFile6}"
rm -rf "${workFile7}"

